﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

public class RecommendationManager
{
    private City city;
    private CityScore cityScore;

    public RecommendationManager(City city, CityScore score)
    {
        this.city = city;
        this.cityScore = score;
    }

    public Recommendation.RecommendationCode GetRecommendation()
    {
        Recommendation.RecommendationCode deterioration = GetDeteriorationRecommendation();
        if (deterioration != Recommendation.RecommendationCode.None) return deterioration;

        Recommendation.RecommendationCode tierRecommendation = GetTierRecommendation();
        if (tierRecommendation != Recommendation.RecommendationCode.None) return tierRecommendation;

        return Recommendation.RecommendationCode.None;
    }

    private Recommendation.RecommendationCode GetTierRecommendation()
    {
        // Tier 1
        List<Recommendation.RecommendationCode> availableTier1Codes = new List<Recommendation.RecommendationCode>();
        if (!cityScore.buildingTypesAlreadyInCity.Contains(Building.BuildingType.Capital)) availableTier1Codes.Add(Recommendation.RecommendationCode.Tier1_Capital);
        if (!cityScore.buildingTypesAlreadyInCity.Contains(Building.BuildingType.FireStation)) availableTier1Codes.Add(Recommendation.RecommendationCode.Tier1_Fire);
        if (!cityScore.buildingTypesAlreadyInCity.Contains(Building.BuildingType.PoliceStation)) availableTier1Codes.Add(Recommendation.RecommendationCode.Tier1_Police);
        if (!cityScore.buildingTypesAlreadyInCity.Contains(Building.BuildingType.Hospital)) availableTier1Codes.Add(Recommendation.RecommendationCode.Tier1_Hospital);
        if (!cityScore.buildingTypesAlreadyInCity.Contains(Building.BuildingType.Farm)) availableTier1Codes.Add(Recommendation.RecommendationCode.Tier1_Farm);
        if (!cityScore.buildingTypesAlreadyInCity.Contains(Building.BuildingType.PowerStation) ) availableTier1Codes.Add(Recommendation.RecommendationCode.Tier1_Power);
        if (!cityScore.buildingTypesAlreadyInCity.Contains(Building.BuildingType.WaterPlant)) availableTier1Codes.Add(Recommendation.RecommendationCode.Tier1_Water);

        if (availableTier1Codes.Count > 0)
        {
            return availableTier1Codes[UnityEngine.Random.Range(0, availableTier1Codes.Count)];
        }


        // Tier 2
        List<Recommendation.RecommendationCode> availableTier2Codes = new List<Recommendation.RecommendationCode>();
        if (!cityScore.buildingTypesAlreadyInCity.Contains(Building.BuildingType.Communications)) availableTier2Codes.Add(Recommendation.RecommendationCode.Tier2_Communications);
        if (!cityScore.buildingTypesAlreadyInCity.Contains(Building.BuildingType.Waste)) availableTier2Codes.Add(Recommendation.RecommendationCode.Tier2_Waste);
        if (!cityScore.buildingTypesAlreadyInCity.Contains(Building.BuildingType.Courthouse)) availableTier2Codes.Add(Recommendation.RecommendationCode.Tier2_Courthouse);
        if (!cityScore.buildingTypesAlreadyInCity.Contains(Building.BuildingType.Ranch)) availableTier2Codes.Add(Recommendation.RecommendationCode.Tier2_Ranch);
        if (!cityScore.buildingTypesAlreadyInCity.Contains(Building.BuildingType.PrimarySchool)) availableTier2Codes.Add(Recommendation.RecommendationCode.Tier2_PrimarySchool);
        if (!cityScore.buildingTypesAlreadyInCity.Contains(Building.BuildingType.Prison)) availableTier2Codes.Add(Recommendation.RecommendationCode.Tier2_Prison);
        if (!cityScore.buildingTypesAlreadyInCity.Contains(Building.BuildingType.GreenPower)) availableTier2Codes.Add(Recommendation.RecommendationCode.Tier2_GreenPower);

        if (availableTier2Codes.Count > 0)
        {
            return availableTier2Codes[UnityEngine.Random.Range(0, availableTier2Codes.Count)];
        }


        // Tier 3
        List<Recommendation.RecommendationCode> availableTier3Codes = new List<Recommendation.RecommendationCode>();
        if (!cityScore.buildingTypesAlreadyInCity.Contains(Building.BuildingType.SecondarySchool)) availableTier3Codes.Add(Recommendation.RecommendationCode.Tier3_SecondarySchool);
        if (!cityScore.buildingTypesAlreadyInCity.Contains(Building.BuildingType.Urban)) availableTier3Codes.Add(Recommendation.RecommendationCode.Tier3_Urban);
        if (!cityScore.buildingTypesAlreadyInCity.Contains(Building.BuildingType.Suburban)) availableTier3Codes.Add(Recommendation.RecommendationCode.Tier3_Suburban);
        if (!cityScore.buildingTypesAlreadyInCity.Contains(Building.BuildingType.Church)) availableTier3Codes.Add(Recommendation.RecommendationCode.Tier3_Church);
        if (!cityScore.buildingTypesAlreadyInCity.Contains(Building.BuildingType.Library)) availableTier3Codes.Add(Recommendation.RecommendationCode.Tier3_Library);

        if (availableTier3Codes.Count > 0)
        {
            return availableTier3Codes[UnityEngine.Random.Range(0, availableTier3Codes.Count)];
        }


        // Tier 4
        List<Recommendation.RecommendationCode> availableTier4Codes = new List<Recommendation.RecommendationCode>();
        if (!cityScore.buildingTypesAlreadyInCity.Contains(Building.BuildingType.Factory)) availableTier4Codes.Add(Recommendation.RecommendationCode.Tier4_Factory);
        if (!cityScore.buildingTypesAlreadyInCity.Contains(Building.BuildingType.Textiles)) availableTier4Codes.Add(Recommendation.RecommendationCode.Tier4_Textile);
        if (!cityScore.buildingTypesAlreadyInCity.Contains(Building.BuildingType.Museum)) availableTier4Codes.Add(Recommendation.RecommendationCode.Tier4_Museum);
        if (!cityScore.buildingTypesAlreadyInCity.Contains(Building.BuildingType.Banks)) availableTier4Codes.Add(Recommendation.RecommendationCode.Tier4_Bank);
        if (!cityScore.buildingTypesAlreadyInCity.Contains(Building.BuildingType.Restaurants)) availableTier4Codes.Add(Recommendation.RecommendationCode.Tier4_Restaurant);
        if (!cityScore.buildingTypesAlreadyInCity.Contains(Building.BuildingType.Fuel)) availableTier4Codes.Add(Recommendation.RecommendationCode.Tier4_Fuel);

        if (availableTier4Codes.Count > 0)
        {
            return availableTier4Codes[UnityEngine.Random.Range(0, availableTier4Codes.Count)];
        }


        // Tier 5
        List<Recommendation.RecommendationCode> availableTier5Codes = new List<Recommendation.RecommendationCode>();
        if (!cityScore.buildingTypesAlreadyInCity.Contains(Building.BuildingType.Zoo)) availableTier5Codes.Add(Recommendation.RecommendationCode.Tier5_Zoo);
        if (!cityScore.buildingTypesAlreadyInCity.Contains(Building.BuildingType.Stadium)) availableTier5Codes.Add(Recommendation.RecommendationCode.Tier5_Stadium);
        if (!cityScore.buildingTypesAlreadyInCity.Contains(Building.BuildingType.Theater)) availableTier5Codes.Add(Recommendation.RecommendationCode.Tier5_Theater);
        if (!cityScore.buildingTypesAlreadyInCity.Contains(Building.BuildingType.BigBoxStore)) availableTier5Codes.Add(Recommendation.RecommendationCode.Tier5_BigBoxStores);
        if (!cityScore.buildingTypesAlreadyInCity.Contains(Building.BuildingType.Mining)) availableTier5Codes.Add(Recommendation.RecommendationCode.Tier5_Mining);
        if (!cityScore.buildingTypesAlreadyInCity.Contains(Building.BuildingType.Lumber)) availableTier5Codes.Add(Recommendation.RecommendationCode.Tier5_Lumber);
        if (!cityScore.buildingTypesAlreadyInCity.Contains(Building.BuildingType.Warehouse)) availableTier5Codes.Add(Recommendation.RecommendationCode.Tier5_Warehouses);

        if (availableTier5Codes.Count > 0)
        {
            return availableTier5Codes[UnityEngine.Random.Range(0, availableTier5Codes.Count)];
        }

        return Recommendation.RecommendationCode.None;
    }

    private Recommendation.RecommendationCode GetDeteriorationRecommendation()
    {
        if (cityScore.turnCount < 15) return Recommendation.RecommendationCode.None;

        float prisonDeterioration = cityScore.prisonDeteriorationPenalty;
        float farmDeterioration = cityScore.foodDeteriorationPenalty;
        float fireDeterioration = cityScore.fireDeteriorationByTile.Values.Sum();
        float policeDeterioration = cityScore.policeDeteriorationByTile.Values.Sum();
        float hospitalDeterioration = cityScore.hospitalDeteriorationByTile.Values.Sum();
        float wasteDeterioration = cityScore.wasteDeteriorationByTile.Values.Sum();
        float waterDeterioration = cityScore.waterDeteriorationByTile.Values.Sum();
        float powerDeterioration = cityScore.powerDeteriorationByTile.Values.Sum();

        List<float> deteriorationTotals = new List<float>();
        deteriorationTotals.Add(prisonDeterioration);
        deteriorationTotals.Add(farmDeterioration);
        deteriorationTotals.Add(fireDeterioration);
        deteriorationTotals.Add(policeDeterioration);
        deteriorationTotals.Add(hospitalDeterioration);
        deteriorationTotals.Add(wasteDeterioration);
        deteriorationTotals.Add(waterDeterioration);
        deteriorationTotals.Add(powerDeterioration);

        deteriorationTotals.Sort();
        if (deteriorationTotals.Last() == prisonDeterioration) return Recommendation.RecommendationCode.Deterioration_Prison;
        if (deteriorationTotals.Last() == farmDeterioration) return Recommendation.RecommendationCode.Deterioration_Farm;
        if (deteriorationTotals.Last() == fireDeterioration) return Recommendation.RecommendationCode.Deterioration_Fire;
        if (deteriorationTotals.Last() == policeDeterioration) return Recommendation.RecommendationCode.Deterioration_Police;
        if (deteriorationTotals.Last() == hospitalDeterioration) return Recommendation.RecommendationCode.Deterioration_Hospital;
        if (deteriorationTotals.Last() == wasteDeterioration) return Recommendation.RecommendationCode.Deterioration_Waste;
        if (deteriorationTotals.Last() == waterDeterioration) return Recommendation.RecommendationCode.Deterioration_Water;
        if (deteriorationTotals.Last() == powerDeterioration) return Recommendation.RecommendationCode.Deterioration_Power;

        return Recommendation.RecommendationCode.None;
    } 
}
